import {
  WebGLRenderer,
  PerspectiveCamera,
  Scene,
  Vector3,
  ACESFilmicToneMapping,
  Object3D,
  Mesh,
  Light,
  Cache,
  // BufferGeometry,
  // LineBasicMaterial,
  // Line,
  Spherical,
} from 'three';
import Stats from 'three/examples/jsm/libs/stats.module';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { Sky } from './Sky';
// import { ModelLoder } from './ModelLoder';
import { AssetManager } from './AssetManager';
// import Vconsole from 'vconsole';
// import { controlPoints } from './CurveConfig';

export class World {
  public worldSceneDom: HTMLElement;
  public sky: Object3D;
  public scene: Scene;
  public camera: PerspectiveCamera;
  public renderer: WebGLRenderer;
  public renderFun: number;
  public control: OrbitControls;
  public controlPoints: number[][];
  public vector3: Vector3;
  // public vconsole: Vconsole;
  private assetManager: AssetManager;
  private stats: Stats;
  constructor() {
    //Renderer
    this.renderer = new WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true, precision: 'highp' });
    this.camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
    // this.vconsole = new Vconsole();
    this.scene = new Scene();

    //orbitControls
    this.control = new OrbitControls(this.camera, this.renderer.domElement);

    this.vector3 = new Vector3();
    //camera
    this.camera.position.set(0, 50, 0);
    this.camera.lookAt(this.vector3);
    this.camera.up = this.vector3.set(0, 1, 0);

    //初始化性能监视器
    this.stats = new Stats();
    //资源管理
    this.assetManager = new AssetManager();
  }

  init(worldSceneDom?: HTMLElement) {
    this.worldSceneDom = worldSceneDom as HTMLElement;
    //Renderer
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);

    this.renderer.toneMapping = ACESFilmicToneMapping;
    this.renderer.toneMappingExposure = 1.0;
    //orbitControls
    // this.control.enableDamping = true;
    // this.control.dampingFactor = 0.1;
    this.control.minDistance = 1; //原点最小距离
    this.control.maxDistance = 100; //原点最大距离
    this.control.maxPolarAngle = Math.PI / 2.2; // 翻转最大角度
    this.control.screenSpacePanning = false; //静止鼠标右键Z轴移动
    //限制相机距离
    this.control.addEventListener('change', () => {
      const target = this.control.target;
      const spherical = new Spherical().setFromVector3(target);
      const maxRadius = 30; // 限制平移范围的最大半径
      const minRadius = 2; // 限制平移范围的最小半径
      const distance = Math.max(minRadius, Math.min(maxRadius, spherical.radius));
      const radius = distance;
      target.setFromSpherical(spherical.set(radius, spherical.phi, spherical.theta));
    });

    //精灵标签

    //stats
    this.stats.dom.style.position = 'fixed';
    this.stats.dom.style.top = '0';
    this.stats.dom.style.right = '5px';
    this.stats.dom.style.left = 'unset';

    const scope = this;
    const onWindowResize = () => {
      scope.camera.aspect = window.innerWidth / window.innerHeight;
      scope.camera.updateProjectionMatrix();
      scope.renderer.setSize(window.innerWidth, window.innerHeight);
    };

    window.addEventListener('resize', onWindowResize, false);
    // this.Curve(controlPoints);
    //创建天空
    this.sky = new Sky(this);

    const renderFun = () => {
      this.renderer.render(this.scene, this.camera);

      this.stats.update();
      this.control.update();

      this.Compass(this.camera, this.control);
      requestAnimationFrame(renderFun);
    };
    renderFun();
    this.worldSceneDom.appendChild(this.stats.dom);
    this.worldSceneDom.appendChild(this.renderer.domElement);
  }
  public add(obj: Object3D) {
    this.scene && this.scene.add(obj);
    this.assetManager && this.assetManager.track(obj);
  }
  public track(obj: THREE.Object3D) {
    return this.assetManager.track(obj);
  }

  private Compass(camera: PerspectiveCamera, control: OrbitControls) {
    const dirx = camera.position.x - control.target.x;
    const dirz = camera.position.z - control.target.z;
    const targetTheta = ((Math.atan2(dirx, dirz) * 180) / Math.PI + 360) % 360; // 将角度限制在0到360范围内
    const compassDom = document.querySelector('.cameraSpin-img') as HTMLImageElement;

    // 获取当前指南针的角度
    let currentTheta = parseInt(compassDom.style.transform.replace('rotateZ(', '').replace('deg)', '')) || 0;
    // 计算平滑后的角度
    let delta = targetTheta - currentTheta;
    if (Math.abs(delta) > 180) {
      // 如果超过180度，则选择更短路径过渡
      delta = delta > 0 ? delta - 360 : delta + 360;
    }
    const smoothTheta = currentTheta + delta * 0.1; // 调整平滑度，可以尝试不同的值

    // 更新指南针的角度
    compassDom.style.transform = `rotateZ(${smoothTheta}deg)`;
    // console.log(smoothTheta);
  }
  // private Curve(controlPoints: number[][]) {
  //   const points: Array<Vector3> = [];
  //   const material = new LineBasicMaterial({ color: 0xff0000 });
  //   controlPoints.forEach((controlPointsi: number[]) => {
  //     points.push(new Vector3(controlPointsi[0], controlPointsi[1], controlPointsi[2]));
  //   });

  //   const geometry = new BufferGeometry();
  //   geometry.setFromPoints(points);
  //   const line = new Line(geometry, material);
  //   // this.add(line);
  // }
  public destroy() {
    this.scene.traverse((obj) => {
      if (obj instanceof Mesh) {
        obj.geometry.dispose();
        obj.material.map?.dispose();
        obj.material.map = null;
        obj.material.dispose();
      }

      if (obj instanceof Light) {
        obj.dispose();
      }
    });
    cancelAnimationFrame(this.renderFun);
    this.assetManager.dispose();
    this.scene.clear();
    this.renderer.renderLists.dispose();
    this.renderer.dispose();
    this.renderer.forceContextLoss();
    this.worldSceneDom.removeChild(this.renderer.domElement);
    Cache.clear();
  }
  public clearMode() {
    this.scene.traverse((obj) => {
      if (obj instanceof Mesh) {
        obj.geometry.dispose();
        obj.material.map?.dispose();
        obj.material.map = null;
        obj.material.dispose();
      }
      if (obj instanceof Light) {
        obj.dispose();
      }
    });

    this.assetManager.dispose();
  }
}
